type EventType = string | symbol;
type EventHandler<T = any> = (params?: T) => void;

type EventHandlerList = Set<EventHandler>;

type EventHandlerMap = Map<EventType, EventHandlerList>;

interface Emmiter {
  on(eventType: EventType, handler: EventHandler): void;
  off(eventType: EventType, handler: EventHandler): void;
  emit(eventType: EventType, params?: any): void;
}

export default class Mitt implements Emmiter {
  public all: EventHandlerMap;
  constructor(all?: EventHandlerMap) {
    this.all = all || (new Map() as EventHandlerMap);
  }
  on(eventType, handler) {
    const handlers = this.all.get(eventType);
    handlers ? handlers.add(handler) : this.all.set(eventType, new Set([handler]));
  }
  off(eventType, handler) {
    const handlers = this.all.get(eventType);
    handlers.delete(handler);
  }
  emit(eventType, params) {
    const handlers = this.all.get(eventType);
    handlers.forEach(handler => {
      handler(params);
    });
  }
}
